import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.awt.Color;
import java.util.List;

/**
 * Write a description of class TestWorld here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class GameWorld extends World
{
    private int scrollx;
    private int terrainNum;
    private int max;
    private int min;
    
    private int level;
    private int lastLevel;
    private int helpIndex=0;
    private int spawnPoint=0;
    
    private int animation;
    private Screen screen=new Screen();
    
    private Player player;
    private Whip whip;
    private CollisionBox colDown;
    private CollisionBox colPlayer;
    private CollisionBox colRight;
    private CollisionBox colLeft;
    private HealthBar healthbar;
    private Lives lives;
    
    private boolean isWorldAnimationPlaying;
    private boolean playedAnimation;
    private boolean debug=false;
    private boolean playedSound;
    private boolean levelChanged=false;
    
    private Timer rockSpawn1=new Timer();
    private Timer rockSpawn2=new Timer();
    private Timer rockSpawn3=new Timer();
    private Timer rockSpawn4=new Timer();
    
    private GreenfootSound[] sound=new GreenfootSound[1];
    
    private GreenfootImage[] ground;
    private GreenfootImage[] ledge;
    private GreenfootImage[] background;
    
    /**
     * Constructor for objects of class TestWorld.
     * 
     */
    public GameWorld()
    {    
        // Create a new world with 720x400 cells with a cell size of 1x1 pixels.
        super(720, 400, 1, false); 
        scrollx = 0;
        terrainNum= 1;
        max= 360;
        min= -360;
        level=1;
        lastLevel=0;
        
        player=new Player();
        whip=new Whip(player);
        colDown=new CollisionBox(player,0,65,10,10);
        colPlayer=new CollisionBox(player,0,0,34,90);
        colRight=new CollisionBox(player,40,0,10,10);
        colLeft=new CollisionBox(player,-40,0,10,10);
        healthbar=new HealthBar();
        lives=new Lives();
        
        Greenfoot.setSpeed(50);
        isWorldAnimationPlaying=false;
        playedAnimation=false;
        playedSound=false;
        
        setBackground(new GreenfootImage("menu.png"));

        //prepare();
        mainMenu();
        setPaintOrder(Screen.class,GUI.class,Lives.class,HealthBar.class,CollisionBox.class,Player.class,Whip.class,Boulder.class,Ground.class);
        setActOrder(Player.class,Whip.class);
        
        sound[0]=new GreenfootSound("level_clear.mp3");
        makeImages();    
    } 

    /**
     * Prepare the world for the start of the program. That is: create the initial
     * objects and add them to the world.
     */
    private void prepare()
    {  
        makeImages();
        
        removeObjects(getObjects(Trap.class));
        removeObjects(getObjects(Ground.class));
        removeObjects(getObjects(Background.class));
        removeObjects(getObjects(Ledge.class));
        removeObjects(getObjects(GUI.class));
        
        addObject(player, getWidth()/2, 260);
        addObject(whip, 0, 0);
        addObject(colDown,getWidth()/2,getHeight()/2);
        addObject(colPlayer,getWidth()/2,getHeight()/2);
        addObject(colRight,getWidth()/2,getHeight()/2);
        addObject(colLeft,getWidth()/2,getHeight()/2);
        addObject(healthbar,0,0);
        addObject(lives,40,60);
        addObject(new GUI(),70,60);
        
        addObject(new Ground(-2),getWidth()/2,getHeight()/2);
        addObject(new Ground(-1),getWidth()/2,getHeight()/2);
        addObject(new Ground(0),getWidth()/2,getHeight()/2);
        addObject(new Ground(1),getWidth()/2,getHeight()/2);
        addObject(new Ground(2),getWidth()/2,getHeight()/2);
        addObject(new Ground(3),getWidth()/2,getHeight()/2);
        
        addObject(new Background(-1),getWidth()/2,getHeight()/2);
        addObject(new Background(0),getWidth()/2,getHeight()/2);
        addObject(new Background(1),getWidth()/2,getHeight()/2);
        addObject(new Background(2),getWidth()/2,getHeight()/2);
        
        addObject(new Ledge(-1),getWidth()/2,getHeight()/2);
        addObject(new Ledge(0),getWidth()/2,getHeight()/2);
        addObject(new Ledge(1),getWidth()/2,getHeight()/2);
        addObject(new Ledge(2),getWidth()/2,getHeight()/2); 
        
        scrollx = 0;
        terrainNum= 1;
        max= 360;
        min= -360;
        
        switch(level)
        {
            case -1:
            
            spawnPoint=0;
            
            //new Trap(positionX,delay between objects/main motion, initial delay to start moving);
        
            //new Rock(positionX,delay between rock, initial delay to start spawning rocks,skin type);
            addObject(new Rock(250,800,0,0),0,0);
            addObject(new Rock(300,800,400,0),0,0);
            addObject(new Rock(350,800,800,0),0,0);
            addObject(new Rock(400,800,1200,0),0,0);
        
            //new Spikes(positionX,delay between pop ups, initial delay to start moving);
            addObject(new Spikes(200,800,0),0,0);
        
            //new Wall(positionX,delay spent on lowest/highest point, initial delay to start moving, highest yPos,lowest yPos, skin);
            addObject(new Wall(-50,800,0,100,getHeight()-100,0),0,-100);
            addObject(new Wall(-150,800,1200,100,getHeight()-100,0),0,-100);
            addObject(new Wall(-250,800,2400,100,getHeight()-100,0),0,-100);
            addObject(new Wall(-350,800,3600,100,getHeight()-100,0),0,-100);
        
            //new Saw(positionX,delay spent on edges of the trayectory, initial delay to start moving, trayectory length);
            addObject(new Saw(200,0,0,100),0,200);
            addObject(new Saw(200,1000,0,100),0,100);
        
            addObject(new Scythe(-600,300,0),-100,0-20);
            break;
        
            case 1:
            
            spawnPoint=0;
            
            setBackground(new GreenfootImage("world_jungle.png"));
            
            addObject(new Rock(480,800,0,1),0,0);
            addObject(new Rock(750,800,400,1),0,0);
            addObject(new Rock(2400,800,0,1),0,0);
            addObject(new Rock(2900,800,400,1),0,0);
            addObject(new Rock(5700,800,0,2),0,0);
            
            addObject(new SnakeSpawner(1180,5000,0),0,0);
            addObject(new SnakeSpawner(2600,4000,0),0,0);
            addObject(new SnakeSpawner(6000,7000,0),0,0);
            
            addObject(new Spikes(6100,1800,400),0,0);
            addObject(new Spikes(6150,1800,800),0,0);
            addObject(new Spikes(6200,1800,1200),0,0);
            addObject(new Spikes(6250,1800,1600),0,0);
            addObject(new Spikes(6300,1800,2000),0,0);
            addObject(new Spikes(6350,1800,2400),0,0);
            addObject(new Spikes(6400,1800,2800),0,0);
            addObject(new Spikes(6450,1800,3200),0,0);
            
            addObject(new BoulderSpawner(5000,2000,0,1,20,2),0,0);
            
            
            addObject(new Wall(5310,1200,0,50,getHeight(),1),0,-100);
            addObject(new Wall(5410,800,4800,50,230,1),0,-100);
            addObject(new Wall(5518,1200,2400,50,getHeight(),1),0,-100);
            
            break;
            
            case 2:
            
            spawnPoint=380;
            scrollx=380;
            
            setBackground(new GreenfootImage("world_mountain.png"));
            
            default:
            break;
        }
    }
    
    public void mainMenu()
    {
        removeObjects(getObjects(null));
        setBackground(new GreenfootImage("menu.png"));
        level=0;
        helpIndex=0;
        addObject(new Play(360,233),360,233);
        addObject(new Help(360,350),360,350);
        addObject(new Scores(130,350),130,350);
        addObject(new Credits(590,350),590,350);
    }
    
    public void play()
    {
        player.reset();
        removeObjects(getObjects(null));
        level=1;
        prepare();
    }
    
    public void showCredits()
    {
    }
    
    public void showScores()
    {
        removeObjects(getObjects(null));
        setBackground(new GreenfootImage("scoreboard.png"));
        addObject(new Return(80,40),80,40);
        
        addObject(new ScoreBoard(720,400),getWidth()/2,getHeight()/2);
    }
    
    public void showHelp()
    {
        removeObjects(getObjects(null));
        helpIndex=0;
        setBackground(new GreenfootImage("help_b0.png"));
        addObject(new Return(80,40),80,40);
        addObject(new Next(360,getHeight()-20),360,getHeight()-20);
        Greenfoot.delay(20);
    }
    
    public void nextPage()
    {
        helpIndex++;
        
        if(helpIndex>=5)
        {
            mainMenu();
            return;
        }
        
        setBackground(new GreenfootImage("help_b"+helpIndex+".png"));  
    }
        
    
    public void act()
    { 
        if(scrollx<=min)
        {
            terrainNum--;
            max-=getWidth();
            min-=getWidth();
        }
        
        if(scrollx>=max)
        {
            terrainNum++;
            max+=getWidth();
            min+=getWidth();
        }
        
        switch(level)
        {
            case 1:     if(scrollx<-6600 && player.isTouchingGround())
                        {
                            isWorldAnimationPlaying=true;
                            animation=3;
                        }
                        break;
            case 2:     if(scrollx<-6700 && player.isTouchingGround())
                        {
                            isWorldAnimationPlaying=true;
                            animation=3;
                        }
                        break;
            default:    break;
        }
        
        
        if(isWorldAnimationPlaying)
        {
            switch(animation)
            {
                case 1:     addObject(screen,360,200);
                            screen.changeType(0);
                                        
                            if(screen.isAppearing()==false)
                            {
                                player.setLocation(player.getX(),getHeight()-135);
                                setScrollx(spawnPoint);
                            }
        
                            if(screen.playedAnimation()==true)
                            {
                                screen.reset();
                                removeObject(screen);
                                isWorldAnimationPlaying=false;
                                playedAnimation=true;
                            }
                            break;
                            
               case 2:      addObject(screen,360,200);
                            screen.changeType(1);
                            
                            if(screen.isSolid()==true)
                            {
                                Greenfoot.delay(500);
                                screen.reset();
                                removeObjects(getObjects(null));
                                isWorldAnimationPlaying=false;
                                playedAnimation=false;
                                player.reset();
                                lives.updateImage(5);
                                setScrollx(spawnPoint);
                                prepare();
                                getLives().updateImage(5);
                                getHealthBar().updateImage(100);
                            }
                            break;
                            
               case 3:      player.rest();
                            player.setInvulnerable(true);
                            
                            if(player.isDoneResting())
                            {
                                addObject(screen,360,200);
                                screen.changeType(0);
                                screen.setDelay(45);
            
                                if(screen.isSolid()==true)
                                {
                                    changeLevel();
                                    
                                    if(level==-1)
                                    return;
                                    
                                    if(level!=-1)
                                    screen.setDelay(1000); 
                                }
                                                        
                                if(screen.playedAnimation()==true)
                                {
                                    screen.reset();
                                    removeObject(screen);
                                    isWorldAnimationPlaying=false;
                                    playedAnimation=false;
                                    playedSound=false;
                                    player.setInvulnerable(false);
                                    levelChanged=false;
                                }
                            }
                            break;
                            
            }
        }  
        
        /*if(Greenfoot.getKey()=="F1")
        {
            if(debug==false)
            debug=true;
            else
            debug=false;
            
            player.setInvulnerable(debug);
        } 
        
        if(debug==true && Greenfoot.isKeyDown("1") && level!=1)
        {
            changeLevel(1);
        }
        
        if(debug==true && Greenfoot.isKeyDown("2") && level!=2)
        {
            changeLevel(2);
        }*/
        
        
    }
    
    public void changeLevel()
    {
        if(levelChanged)
        return;
        
        switch(level)
        {
            case 1:     level=2;
                         break;
            case 2:     level=-1;
                        break;
            default:    break;
        }
                                    
        if(level==-1)
        {
            if(!playedSound)
            {
                sound[0].play();  
                playedSound=true;
            }
                                            
            player.calculateScore();
            Greenfoot.delay(200);
            screen.reset();
            removeObject(screen);
            isWorldAnimationPlaying=false;
            playedAnimation=false;
            playedSound=false;
            player.setInvulnerable(false);
            removeObjects(getObjects(null));
            showScores();
            return;
        }
        
        levelChanged=true;
        prepare();
    }
    
    public void changeLevel(int l)
    {
        level=l;
        prepare();
    }

                                        
    public void makeImages()
    {
        ground=null;
        background=null;
        ledge=null;
        
        ground=new GreenfootImage[20];
        background=new GreenfootImage[20];
        ledge=new GreenfootImage[20];
        
        switch(level)
        {
            case -1:
            case 1:     for(int i=0;i<=10;i++)
                        {
                            ground[i]=new GreenfootImage("ground_jungle"+i+".png");
                            background[i]=new GreenfootImage("background_jungle"+i+".png");
                            ledge[i]=new GreenfootImage("ledge_jungle"+i+".png");
                        }
                        break;
           case 2:      for(int i=0;i<=10;i++)
                        {
                            ground[i]=new GreenfootImage("ground_mountain"+i+".png");
                            background[i]=new GreenfootImage("background_mountain"+i+".png");
                            ledge[i]=new GreenfootImage("ledge_mountain"+i+".png");
                        }
                        break;
        }
    }
    
    public GreenfootImage getImage(int type,int index)
    {
        if(index<0 || index>10)
            switch(level)
            {
                case 1:     return(new GreenfootImage("water.png"));
                case 2:     return(new GreenfootImage(10,10));
                default:     return(new GreenfootImage(10,10));
            }
        
        switch(type)
        {
            case 1:     return(ground[index]);
            case 2:     return(background[index]);
            case 3:     return(ledge[index]);
            default:    return(new GreenfootImage(10,10));
        }
    }
    
    public void resetScore()
    {
        if(UserInfo.isStorageAvailable())
        {
            java.util.List<UserInfo> users=UserInfo.getTop(0);
            
            if(!users.isEmpty())
                for(int i=0;i<users.size();i++)
                {
                    users.get(i).setScore(0);
                    users.get(i).store();
                }
        }
    }
                
                
    
    public void playAnimation(int num)
    {
        animation=num;
        isWorldAnimationPlaying=true;
    }
    
    public void setLevel(int num)
    {
        level=num;
    }
           
    public Player getPlayer()
    {
        return(player);
    }
    
    public Whip getWhip()
    {
        return(whip);
    }
    
    public CollisionBox getColDown()
    {
        return(colDown);
    }
    
    public CollisionBox getColRight()
    {
        return(colRight);
    }
    
    public CollisionBox getColLeft()
    {
        return(colLeft);
    }
    
    public CollisionBox getColPlayer()
    {
        return(colPlayer);
    }
    
    public HealthBar getHealthBar()
    {
        return(healthbar);
    }
    
    public Lives getLives()
    {
        return(lives);
    }
    
    public int getScrollx()
    {
        return(scrollx);
    }
    
    public void setScrollx(int num)
    {
        scrollx=num;
    }
    
    public void changeScrollx(int num)
    {
        scrollx=scrollx+num;
    }
    
    public int getTerrainNum()
    {
        return(terrainNum);
    }
    
    public void setTerrainNum(int num)
    {
        terrainNum=num;
    }
    
    public boolean isWorldAnimationPlaying()
    {
        return(isWorldAnimationPlaying);
    }
    
    public boolean playedAnimation()
    {
        return(playedAnimation);
    }
    
    public void resetAnimation()
    {
        playedAnimation=false;
    }
    
    public void removeSnakes()
    {
        java.util.List<Snake> list=getObjects(Snake.class);
        
        for(int i=0;i<list.size();i++)
        list.get(i).kill();
    }
    
    public boolean isDebugOn()
    {
        return(debug);
    }
}
    
